package cz.pecinovsky.english.pojj.adv_demo.cesta_školou.hra;

import cz.pecinovsky.english.pojj.adv_framework.game_gui.IBagG;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.IListener;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.IPlaceG;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.Commands;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.IGameG;

import cz.pecinovsky.english.pojj.adv_framework.game_txt.ICommand;

import cz.pecinovsky.english.pojj.adv_framework.scenario.AScenarioManager;

import java.net.URL;

import java.util.Collection;

import javax.swing.ImageIcon;

import static cz.pecinovsky.english.pojj.adv_demo.cesta_školou.hra.SS_CestaSkolou.*;


/**
 *  Třída HraCestaSkolou - třída představující logiku adventury.
 *
 *  Toto je hlavní třída  logiky aplikace.
 *  Tato třída vytváří instanci třídy HerniPlan,
 *  která inicializuje mistnosti hry a vytváří
 *  seznam platných příkazů a instance tříd provádějící jednotlivé příkazy.
 *  Vypisuje uvítací a ukončovací text hry.
 *  Také vyhodnocuje jednotlivé příkazy zadané uživatelem.
 *
 * @author     Michael Kolling, Lubos Pavlicek, Jarmila Pavlickova, Rudolf Pecinovský
 * @version    5.0, říjen 2010 (poslední změny)
 */

public class HraCestaSkolou
      implements IGameG   //+++ Přidáno pro zařazení do rámce
{
    //+++ Přidáno pro zařazení do rámce
    /** Názvy čtyř základních povinných příkazů každé hry. */
    private static final Commands příkazy =
                     new Commands(pJDI, pPOLOŽ, pZVEDNI, pKONEC);

    /** Správce scénářů, s jejichž pomocí je možno hru testovat
     * nebo domonstrovat její možný průběh. */
    private final AScenarioManager správceScénářů = SS_CestaSkolou.getInstance();

    private Batoh batoh;

    private SeznamPrikazu platnePrikazy;    // obsahuje seznam přípustných slov
    private HerniPlan herniPlan;
    private boolean   konecHry = true;
    //Předchozí hodnota byla nastavena tak, aby byla hra do svého odstartování
    //považována z nefunkční, tj. ekvivalent ukončené


    private static final HraCestaSkolou jedináček = new HraCestaSkolou();
    /***************************************************************************
     * Vrátí jedinou existující instanci této třídy.
     *
     * @return Jediná existující instance této třídy
     */
    public static HraCestaSkolou getHra()
    {
        return jedináček;
    }


//===== METODY Z PŮVODNÍ VERZE (V PŘÍPADĚ POTŘEBY VIDITELNĚ UPRAVENÉ) ==========

    /**
     *  Vytváří hru a inicializuje místnosti (prostřednictvím třídy HerniPlan) a seznam platných příkazů.
     */
    private HraCestaSkolou() {
        //Pro umožnění restartu hry bylo tělo konstruktoru přemístěno
        //do metody zpracujStart(String) startující hru.
    }


    /**
     *  Vrátí úvodní zprávu pro hráče.
     * @return
     */
    public String vratUvitani() {
        return zUVÍTÁNÍ + //+++ Konstanta pro sjednocení se scénářem
               herniPlan.getAktualniMistnost().dlouhyPopis();
    }

    /**
     *  Vrátí závěrečnou zprávu pro hráče.
     * @return
     */
    public String vratEpilog() {
        return "Dik, ze jste si zahrali.  Ahoj.";
    }

    /**
     * Vrací true, pokud hra skončila.
     * @return
     */
     public boolean konecHry() {
        return konecHry;
    }

    /**
     *  Metoda zpracuje řetězec uvedený jako parametr, rozdělí ho na slovo příkazu a další parametry.
     *  Pak otestuje zda příkaz je klíčovým slovem  např. jdi.
     *  Pokud ano spustí samotné provádění příkazu.
     *
     *@param  radek  text, který zadal uživatel jako příkaz do hry.
     *@return          vrací se řetězec, který se má vypsat na obrazovku
     */
    public String zpracujPrikaz(String radek) {

        //+++ Upraveno pro zařazení do rámce
        if (isReady()) {
            return zpracujStart(radek);                      //==========>
        }
        //--- Konec úpravy

        String [] slova = radek.split("[ \t]+");
        String slovoPrikazu = slova[0];
        String []parametry = new String[slova.length-1];
        for(int i=0 ;i<parametry.length;i++){
           	parametry[i]= slova[i+1];
        }
        if (platnePrikazy.jePlatnyPrikaz(slovoPrikazu)) {
            Prikaz prikaz = platnePrikazy.vratPrikaz(slovoPrikazu);
            String textKVypsani = prikaz.proved(parametry);
            return textKVypsani;                            //==========>
        }
        else {
            if ("".equals(radek.trim())) {
                return zNIC;                               //==========>
            }
            else {
                return zNEZNÁM_AKCI;                       //==========>
            }
        }
    }


    /**
     *  Nastaví, že je konec hry, metodu využívá třída PrikazKonec,
     *  mohou ji použít i další implementace rozhraní Prikaz.
     *
     *  @param  konecHry  hodnota false= konec hry, true = hra pokračuje
     */
    void setKonecHry(boolean konecHry) {
        this.konecHry = konecHry;
    }

     /**
     *  Metoda vrátí odkaz na herní plán, je využita hlavně v testech,
     *  kde se jejím prostřednictvím získává aktualní místnost hry.
     *
     *  @return     odkaz na herní plán
     */
     HerniPlan getHerniPlan(){
        return herniPlan;
     }



//== METODY VYŽADOVANÉ IMPLEMENTOVANÝM ROZHRANÍM Z RÁMCE 101 ===================

    /***************************************************************************
     * Vrátí jméno autora scénáře ve formátu "PŘÍJMENÍ Křestní",
     * tj. neprve příjmení psané velkými písmeny a za ním křestní jméno,
     * u nějž bude velké pouze první písmeno a ostatní písmena budou malá.
     *
     * @return Jméno autora/autorky programu ve tvaru PŘÍJMENÍ Křestní
     */
    @Override
    public String getAuthor()
    {
//        return "KOLEKTIV Autorů";
        return správceScénářů.getAuthor();
    }


    /***************************************************************************
     * Vrátí x-name autora/autorky programu zapsané velkými písmeny.<p>
     *
     * @return X-name autora/autorky programu
     */
    @Override
    public String getXNAME()
    {
//        return "XKOLA000";
        return správceScénářů.getXNAME();
    }


    /***************************************************************************
     * Vrátí správce scénářů, které umožní prověřit funkčnost hry
     * a/nebo demonstrovat její průběh.
     *
     * @return Správce scénářů dané hry
     */
    @Override
    public AScenarioManager getScenarioManager()
    {
        return správceScénářů;
    }


    /***************************************************************************
     * Vrátí odkaz na aktuální místnost,
     * tj. na místnost, v niž se pravé nachází hráč.
     *
     * @return Požadovaný odkaz
     */
    @Override
    public Mistnost getActualPlace()
    {
        return herniPlan.getAktualniMistnost();
    }


    /***************************************************************************
     * Vrátí odkaz na batoh, do nějž bude hráč ukládat sebrané předměty.
     *
     * @return Požadovaný odkaz
     */
    @Override
    public Batoh getBag()
    {
        return batoh;
    }


    /***************************************************************************
     * Vrátí kolekci odkazů na jednotlivé místnosti.
     *
     * @return Požadovaná kolekce
     */
    @Override
    public Collection<Mistnost> getAllPlaces()
    {
        return herniPlan.getMístnosti();
    }


    /***************************************************************************
     * Vrátí kolekci všech příkazů použitelných ve hře.
     *
     * @return Požadovaná kolekce
     */
    @Override
    public Collection<? extends ICommand> getAllCommands()
    {
        return platnePrikazy.getPříkazy();
    }


    /***************************************************************************
     * Vrátí informaci o tom, je-li hra již ukončena.
     *
     * @return Požadovaná informace
     */
    @Override
    public boolean isReady()
    {
        return konecHry;
    }


    /***************************************************************************
     * Ukončí celou hru a vrátí alokované prostředky.
     */
    @Override
    public void stop()
    {
        setKonecHry(true);
    }


    /***************************************************************************
     * Zpracuje zadaný příkaz a vrátí text zprávy pro uživatele.
     *
     * @param příkaz Zadávaný příkaz
     * @return Textová odpověď hry na zadaný příkaz
     */
    @Override
    public String executeCommand(String příkaz)
    {
        return zpracujPrikaz(příkaz);
    }


//===== PŘIDANÉ SOUKROMÉ METODY ================================================

    /***************************************************************************
     * Očekává startovací příkaz a vrátí příslušný text.
     * Pokud nebyl zadán startovací příkaz, upozorní na to hráče.
     *
     * @param radek Zadaný příkaz
     * @return Odpověď na zadaný příkaz
     */
    private String zpracujStart(String radek)
    {
        if ("".equals(radek)) {
            setKonecHry(false);
            herniPlan = new HerniPlan(this);
            platnePrikazy = new SeznamPrikazu();
            platnePrikazy.vlozPrikaz(new PrikazNapoveda(platnePrikazy));
            platnePrikazy.vlozPrikaz(new PrikazJdi(herniPlan));
            platnePrikazy.vlozPrikaz(new PrikazKonec(this));

            //+++ Přidáno pro zařazení do rámce
            batoh = new Batoh("Peníze");

            platnePrikazy.vlozPrikaz(new PrikazPoloz(herniPlan));
            platnePrikazy.vlozPrikaz(new PrikazVezmi(herniPlan));
            //--- Konec úpravy

            return vratUvitani();               //==========>
        }
        return "Po ukončení hry není možno zadávat běžné příkazy.";
    }



//== METODY VYŽADOVANÉ IMPLEMENTOVANÝM ROZHRANÍM PRO 115 =======================

    /***************************************************************************
     * Vrátí vstupní znakový proud obsahující stránku s nápovědou.
     *
     * @return Požadovaný odkaz
     */
    @Override
    public URL getHelpURL()
    {
        //TODO Operace ještě není implementována getHelpURL()
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Vrátí obrázek s plánkem prostoru, v němž se hraje.
     *
     * @return Požadovaný odkaz
     */
    @Override
    public ImageIcon getMap()
    {
        //TODO Operace ještě není implementována getMap()
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Vrátí odkaz na přepravku s názvy příkazů pro přesun do jiné místnosti,
     * zvednutí předmětu a jeho položení.
     *
     * @return Požadovaný odkaz
     */
    @Override
    public Commands getBasicCommands()
    {
        return příkazy;
    }


    /***************************************************************************
     * Přidá zadaného posluchače do seznamu posluchačů,
     * které zpravuje o změně množiny předmětů v batohu.
     *
     * @param listener Přihlašovaný posluchač
     */
    @Override
    public void addBagListener(IListener<IBagG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Odebere zadaného posluchače ze seznamu posluchačů,
     * které zpravuje o změně množiny předmětů v batohu.
     *
     * @param listener Odhlašovaný posluchač
     */
    @Override
    public void removeBagListener(IListener<IBagG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Přidá zadaného posluchače do seznamu posluchačů,
     * které zpravuje o změně množiny předmětů v aktuální místnosti.
     *
     * @param listener Přihlašovaný posluchač
     */
    @Override
    public void addObjectListener(IListener<IPlaceG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Odebere zadaného posluchače ze seznamu posluchačů,
     * které zpravuje o změně množiny předmětů v aktuální místnosti.
     *
     * @param listener Odhlašovaný posluchač
     */
    @Override
    public void removeObjectListener(IListener<IPlaceG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Přidá zadaného posluchače do seznamu posluchačů,
     * které zpravuje o změně množiny sousedů aktuální místnosti.
     *
     * @param listener Přihlašovaný posluchač
     */
    @Override
    public void addNeighborsListener(IListener<IPlaceG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Odebere zadaného posluchače ze seznamu posluchačů,
     * které zpravuje o změně množiny sousedů aktuální místnosti.
     *
     * @param listener Odhlašovaný posluchač
     */
    @Override
    public void removeNeighborsListener(IListener<IPlaceG> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Přidá zadaného posluchače do seznamu posluchačů,
     * kterým hra oznamuje začátek a konec rozhovoru.
     *
     * @param listener Přihlašovaný posluchač
     */
    @Override
    public void addDialogListener(IListener<Boolean> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }


    /***************************************************************************
     * Odebere zadaného posluchače ze seznamu posluchačů,
     * kterým hra oznamuje začátek a konec rozhovoru.
     *
     * @param listener Odhlašovaný posluchač
     */
    @Override
    public void removeDialogListener(IListener<Boolean> listener)
    {
        //TODO Operace ještě není implementována
        throw new UnsupportedOperationException("Prozatím neimplementováno");
    }



}

